package cn.ug.operation.service.impl;

import cn.ug.activity.bean.CouponRepertoryBean;
import cn.ug.bean.base.SerializeObject;
import cn.ug.bean.type.ResultType;
import cn.ug.config.RedisGlobalLock;
import cn.ug.core.SerializeObjectError;
import cn.ug.core.ensure.Ensure;
import cn.ug.enums.LotteryPrizeTypeEnum;
import cn.ug.feign.CouponRepertoryService;
import cn.ug.feign.MemberAccountService;
import cn.ug.feign.MemberGoldService;
import cn.ug.feign.MemberUserService;
import cn.ug.member.bean.response.MemberUserBean;
import cn.ug.msg.mq.Msg;
import cn.ug.operation.bean.*;
import cn.ug.operation.mapper.LotteryJoinMemberMapper;
import cn.ug.operation.mapper.LotteryMemberMapper;
import cn.ug.operation.mapper.LotteryPrizeMapper;
import cn.ug.operation.mapper.LotteryShareStatisticsMapper;
import cn.ug.operation.mapper.entity.LotteryJoinMember;
import cn.ug.operation.mapper.entity.LotteryMember;
import cn.ug.operation.mapper.entity.LotteryPrize;
import cn.ug.operation.mapper.entity.LotteryShareStatistics;
import cn.ug.operation.service.LotteryJoinMemberService;
import cn.ug.pay.bean.type.BillGoldTradeType;
import cn.ug.pay.bean.type.TradeType;
import cn.ug.util.DateUtils;
import cn.ug.util.UF;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.dozer.DozerBeanMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;

import static cn.ug.config.QueueName.QUEUE_MSG_SEND;
import static cn.ug.util.ConstantUtil.*;
import static cn.ug.util.RedisConstantUtil.*;

@Service
public class LotteryJoinMemberServiceImpl implements LotteryJoinMemberService {
    @Autowired
    private LotteryJoinMemberMapper lotteryJoinMemberMapper;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @Autowired
    private LotteryMemberMapper lotteryMemberMapper;
    @Autowired
    private RedisGlobalLock redisGlobalLock;
    @Autowired
    private LotteryPrizeMapper lotteryPrizeMapper;
    @Autowired
    private MemberGoldService memberGoldService;
    @Autowired
    private AmqpTemplate amqpTemplate;
    @Autowired
    private MemberUserService memberUserService;
    @Autowired
    private MemberAccountService memberAccountService;
    @Autowired
    private CouponRepertoryService couponRepertoryService;
    @Autowired
    private LotteryShareStatisticsMapper lotteryShareStatisticsMapper;
    @Resource
    private DozerBeanMapper dozerBeanMapper;

    private static Logger logger = LoggerFactory.getLogger(LotteryJoinMemberServiceImpl.class);

    @Override
    public List<LotteryJoinMemberBean> queryForStatistics(int lotteryId, String cellphone, String memberName, String channelId, String order, String sort, int offset, int size) {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("lotteryId", lotteryId);
        if (StringUtils.isNotBlank(cellphone)) {
            params.put("cellphone", cellphone);
        }
        if (StringUtils.isNotBlank(memberName)) {
            params.put("memberName", memberName);
        }
        if (StringUtils.isNotBlank(channelId)) {
            params.put("channelId", channelId);
        }
        if (StringUtils.isNotBlank(order) && (StringUtils.equals(order, "transactionNum") || StringUtils.equals(order, "prizeNum"))) {
            params.put("order", order);
            if (StringUtils.isNotBlank(sort) && (StringUtils.equalsIgnoreCase(sort, "asc") || StringUtils.equalsIgnoreCase(sort, "desc"))) {
                params.put("sort", sort);
            } else {
                params.put("sort", "desc");
            }
        }
        params.put("offset", offset);
        params.put("size", size);
        return lotteryJoinMemberMapper.queryForStatistics(params);
    }

    @Override
    public int countForStatistics(int lotteryId, String cellphone, String memberName, String channelId) {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("lotteryId", lotteryId);
        if (StringUtils.isNotBlank(cellphone)) {
            params.put("cellphone", cellphone);
        }
        if (StringUtils.isNotBlank(memberName)) {
            params.put("memberName", memberName);
        }
        if (StringUtils.isNotBlank(channelId)) {
            params.put("channelId", channelId);
        }
        return lotteryJoinMemberMapper.countForStatistics(params);
    }

    @Override
    public List<LotteryAnalysisDetailBean> queryForAnalysisDetail(int lotteryId, String startDate, String endDate, int offset, int size) {
        if (lotteryId < 1) {
            return null;
        }
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("lotteryId", lotteryId);
        if (StringUtils.isNotBlank(startDate)) {
            params.put("startDate", startDate);
        }
        if (StringUtils.isNotBlank(endDate)) {
            params.put("endDate", endDate);
        }
        params.put("offset", offset);
        params.put("size", size);
        return lotteryJoinMemberMapper.queryForAnalysisDetail(params);
    }

    @Override
    public int countForAnalysisDetail(int lotteryId, String startDate, String endDate) {
        if (lotteryId < 1) {
            return 0;
        }
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("lotteryId", lotteryId);
        if (StringUtils.isNotBlank(startDate)) {
            params.put("startDate", startDate);
        }
        if (StringUtils.isNotBlank(endDate)) {
            params.put("endDate", endDate);
        }
        return lotteryJoinMemberMapper.countForAnalysisDetail(params);
    }

    @Override
    public List<EverydayPrizeBean> queryForEverydayPrizes(int lotteryId, String drawDate, int offset, int size) {
        if (lotteryId > 0 && StringUtils.isNotBlank(drawDate)) {
            Map<String, Object> params = new HashMap<String, Object>();
            params.put("lotteryId", lotteryId);
            params.put("offset", offset);
            params.put("size", size);
            if (StringUtils.isNotBlank(drawDate)) {
                params.put("drawDate", drawDate);
            }
            return lotteryJoinMemberMapper.queryForEverydayPrizes(params);
        }
        return null;
    }

    @Override
    public int countForEverydayPrizes(int lotteryId, String drawDate) {
        if (lotteryId > 0 && StringUtils.isNotBlank(drawDate)) {
            Map<String, Object> params = new HashMap<String, Object>();
            params.put("lotteryId", lotteryId);
            if (StringUtils.isNotBlank(drawDate)) {
                params.put("drawDate", drawDate);
            }
            return lotteryJoinMemberMapper.countForEverydayPrizes(params);
        }
        return 0;
    }

    @Override
    public SerializeObject save(LotteryJoinMember lotteryJoinMember) {
        if (lotteryJoinMember != null) {
            int num = lotteryJoinMemberMapper.isJoined(lotteryJoinMember.getMemberId(), lotteryJoinMember.getLotteryId());
            if (num > 0) {
                //return new SerializeObjectError("00000004");
                return new SerializeObject(ResultType.NORMAL, "00000001");
            }
            int rows = lotteryJoinMemberMapper.insert(lotteryJoinMember);
            if (rows > 0) {
                return new SerializeObject(ResultType.NORMAL, "00000001");
            }
        }
        return new SerializeObjectError("00000005");
    }

    @Override
    public SerializeObject share(String memberId, LotteryBean lottery,int type) {
        LotteryShareStatistics lotteryShareStatistics = new LotteryShareStatistics();
        lotteryShareStatistics.setLotteryId(lottery.getId());
        lotteryShareStatistics.setMemberId(memberId);
        lotteryShareStatisticsMapper.insert(lotteryShareStatistics);

        SimpleDateFormat dateFormat = new SimpleDateFormat(NORMAL_DATE_FORMAT);
        String key = LOTTERY_SHARE_DRAW_NUM_KEY + dateFormat.format(Calendar.getInstance().getTime()) + COLON + memberId+COLON+lottery.getId();
        String value = redisTemplate.opsForValue().get(key);
        int gotNum = 0;
        if (StringUtils.isNotBlank(value)) {
            gotNum = Integer.parseInt(value);
            if (gotNum >= lottery.getEverydayMaxNum()) {
                return new SerializeObjectError("25000061");
            }
        }
        String shareKey = LOTTERY_SHARE_NUM_KEY + dateFormat.format(Calendar.getInstance().getTime()) + COLON + memberId;
        if (lottery.getShareNum() > 1) {
            String shareValue = redisTemplate.opsForValue().get(key);
            int shareNum = 0;
            if (StringUtils.isNotBlank(shareValue)) {
                shareNum = Integer.parseInt(shareValue);
                if (shareNum < lottery.getShareNum()) {
                    shareNum++;
                    redisTemplate.opsForValue().set(shareKey, String.valueOf(shareNum));
                    return new SerializeObject(ResultType.NORMAL, "00000001");
                }
            } else {
                shareNum++;
                redisTemplate.opsForValue().set(shareKey, String.valueOf(shareNum));
                return new SerializeObject(ResultType.NORMAL, "00000001");
            }
        }

        if (StringUtils.isNotBlank(value) && type == 1){
            return new SerializeObject(ResultType.NORMAL, "00000001");
        }
        int rows = lotteryJoinMemberMapper.autoIncreasingTimes(memberId, lottery.getId());
        if (rows > 0) {
            if (lottery.getShareNum() > 1) {
                redisTemplate.opsForValue().set(shareKey, String.valueOf(0));
            }
            gotNum++;
            redisTemplate.opsForValue().set(key, String.valueOf(gotNum));
            return new SerializeObject(ResultType.NORMAL, "00000001");
        } else {
            return new SerializeObjectError("00000005");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public SerializeObject draw(String memberId, LotteryBean lottery) {
        SerializeObject<MemberUserBean> memberBean = memberUserService.findById(memberId);
        String mobile = "";
        if (memberBean != null && memberBean.getData() != null) {
            MemberUserBean memberUserBean = memberBean.getData();
            mobile = memberUserBean.getMobile();
        } else {
            return new SerializeObject(ResultType.ERROR, "00000005");
        }
        String lockKey = "ug:operation:LotteryJoinMemberServiceImpl:draw:"+memberId;
        try {
            if(redisGlobalLock.lock(lockKey, 5000, TimeUnit.MILLISECONDS)) {

                LotteryJoinMember lotteryJoinMember = lotteryJoinMemberMapper.findByMemberId(memberId, lottery.getId());
                if (lotteryJoinMember == null) {
                    return new SerializeObjectError("25000062");
                }
                if (lotteryJoinMember.getTimes() == 0) {
                    SimpleDateFormat dateFormat = new SimpleDateFormat(NORMAL_DATE_FORMAT);
                    String key = LOTTERY_SHARE_DRAW_NUM_KEY + dateFormat.format(Calendar.getInstance().getTime()) + COLON + memberId+COLON+lottery.getId();
                    String value = redisTemplate.opsForValue().get(key);
                    Map params = new HashMap();
                    params.put("memberId",memberId);
                    params.put("lotteryId",lottery.getId());
                    int outModedLotteryNum = lotteryMemberMapper.countLotteryNum(params);
                    if (StringUtils.isNotBlank(value)) {
                        int gotNum = Integer.parseInt(value);
                        if (outModedLotteryNum>0 && lottery.getEverydayNum()==0){
                            return new SerializeObject(501, "25000073");
                        }
                        if (gotNum >= lottery.getEverydayMaxNum()) {
                            return new SerializeObject(502, "25000072");
                        }
                    }
                    if (outModedLotteryNum>0){
                        return new SerializeObject(501, "25000073");
                    }else {
                        return new SerializeObject(502, "25000072");
                    }
                }
                List<LotteryPrize> prizes = lotteryPrizeMapper.selectByLotteryId(lottery.getId());
                if (prizes == null || prizes.size() == 0) {
                    return new SerializeObjectError("00000002");
                }
                List<LotteryPrize> drawPrizes = new ArrayList<LotteryPrize>();
                for (LotteryPrize prize : prizes) {
                    if (prize.getQuantityLimit() == 0) {
                        drawPrizes.add(prize);
                    } else if (prize.getQuantity() > 0) {
                        drawPrizes.add(prize);
                    }
                }
                if (drawPrizes == null || drawPrizes.size() == 0) {
                    return new SerializeObjectError("25000065");
                }
                LotteryPrize prize = getPrize(drawPrizes);
                LotteryMember lotteryMember = new LotteryMember();
                lotteryMember.setAddTime(LocalDateTime.now());
                if (lottery.getGrantingMethod() == 0) {
                    lotteryMember.setGetTime(LocalDateTime.now());
                    lotteryMember.setStatus(1);
                }
                lotteryMember.setLotteryId(lottery.getId());
                lotteryMember.setMemberId(memberId);
                lotteryMember.setPrizeId(prize.getId());
                if (prize.getType() != LotteryPrizeTypeEnum.UN_PRIZE.getType()) {
                    lotteryMember.setRewardsStatus(1);
                }
                int rows = lotteryMemberMapper.insert(lotteryMember);
                if (rows > 0) {
                    if (prize.getQuantityLimit() != 0) {
                        rows = lotteryPrizeMapper.decreaseQuantity(prize.getId());
                        Ensure.that(rows).isLt(1,"00000005");
                    }
                    rows = lotteryJoinMemberMapper.decreaseTimes(memberId, lottery.getId());
                    Ensure.that(rows).isLt(1,"00000005");
                    double amount = 0;
                    if (lottery.getGrantingMethod() == 0) {
                        if (prize.getType() == LotteryPrizeTypeEnum.CASH.getType()) {
                            SerializeObject bean = memberAccountService.inviteReturnCash(memberId, prize.getAmount(), TradeType.CASH_REWARDS.getValue());
                            if(bean != null && bean.getCode() == ResultType.NORMAL) {
                                amount = prize.getAmount().doubleValue();
                                Msg msg = new Msg();
                                msg.setMemberId(memberId);
                                msg.setMobile(mobile);
                                msg.setType(cn.ug.msg.bean.status.CommonConstants.MsgType.CASH_REWARDS.getIndex());
                                Map<String, String> paramMap = new HashMap<>();
                                paramMap.put("amount", String.valueOf(prize.getAmount()));
                                msg.setParamMap(paramMap);
                                amqpTemplate.convertAndSend(QUEUE_MSG_SEND, msg);
                            } else {
                                Ensure.that(0).isLt(1,"00000005");
                            }
                        } else if (prize.getType() == LotteryPrizeTypeEnum.GOLD.getType()) {
                            int tradeType = BillGoldTradeType.LOTTERY.getValue();
                            SerializeObject bean = memberGoldService.investRebate(memberId, prize.getAmount(), tradeType);
                            if(bean != null && bean.getCode() == ResultType.NORMAL) {
                                amount = prize.getAmount().doubleValue();
                                Msg msg = new Msg();
                                msg.setMemberId(memberId);
                                msg.setMobile(mobile);
                                msg.setType(cn.ug.msg.bean.status.CommonConstants.MsgType.GUESS_GOLD_PRICE.getIndex());
                                Map<String, String> paramMap = new HashMap<>();
                                paramMap.put("weight", String.valueOf(prize.getAmount()));
                                msg.setParamMap(paramMap);
                                amqpTemplate.convertAndSend(QUEUE_MSG_SEND, msg);
                            } else {
                                Ensure.that(0).isLt(1,"00000005");
                            }
                        } else if (prize.getType() == LotteryPrizeTypeEnum.KICKBACK.getType()) {
                            if (StringUtils.isBlank(prize.getCouponIds())) {
                                Ensure.that(0).isLt(1,"00000002");
                            }
                            String[] infos = StringUtils.split(prize.getCouponIds(), COMMA);
                            int num = ThreadLocalRandom.current().nextInt(0, infos.length);
                            String couponId = infos[num];
                            SerializeObject bean = couponRepertoryService.giveCoupon(memberId, couponId);
                            if(bean != null && bean.getCode() == ResultType.NORMAL && bean.getData() != null) {
                                amount = Double.parseDouble(bean.getData().toString());
                                Msg msg = new Msg();
                                msg.setMemberId(memberId);
                                msg.setMobile(mobile);
                                msg.setType(cn.ug.msg.bean.status.CommonConstants.MsgType.COUPON_NOTIFY.getIndex());
                                Map<String, String> paramMap = new HashMap<>();
                                paramMap.put("activityName", lottery.getName());
                                paramMap.put("amount", bean.getData().toString());
                                msg.setParamMap(paramMap);
                                amqpTemplate.convertAndSend(QUEUE_MSG_SEND, msg);
                            } else {
                                Ensure.that(0).isLt(1,"00000005");
                            }
                        } else if (prize.getType() == LotteryPrizeTypeEnum.INTEREST.getType()) {
                            if (StringUtils.isBlank(prize.getCouponIds())) {
                                Ensure.that(0).isLt(1,"00000002");
                            }
                            String[] infos = StringUtils.split(prize.getCouponIds(), COMMA);
                            int num = ThreadLocalRandom.current().nextInt(0, infos.length);
                            String couponId = infos[num];
                            SerializeObject bean = couponRepertoryService.giveCoupon(memberId, couponId);
                            if(bean != null && bean.getCode() == ResultType.NORMAL && bean.getData() != null) {
                                amount = Double.parseDouble(bean.getData().toString());
                                Msg msg = new Msg();
                                msg.setMemberId(memberId);
                                msg.setMobile(mobile);
                                msg.setType(cn.ug.msg.bean.status.CommonConstants.MsgType.TICKET_NOTIFY.getIndex());
                                Map<String, String> paramMap = new HashMap<>();
                                paramMap.put("activityName", lottery.getName());
                                paramMap.put("amount", bean.getData().toString());
                                msg.setParamMap(paramMap);
                                amqpTemplate.convertAndSend(QUEUE_MSG_SEND, msg);
                            } else {
                                Ensure.that(0).isLt(1,"00000005");
                            }
                        }
                    }
                    lotteryMember.setAmount(amount);
                    lotteryMemberMapper.update(lotteryMember);
                    JSONObject result = new JSONObject();
                    result.put("prizeName", prize.getName());
                    result.put("amount", amount);
                    result.put("type", prize.getType());
                    SimpleDateFormat dateFormat = new SimpleDateFormat(NORMAL_DATE_FORMAT);
                    String key = LOTTERY_SHARE_DRAW_NUM_KEY + dateFormat.format(Calendar.getInstance().getTime()) + COLON + memberId+COLON+lottery.getId();
                    String value = redisTemplate.opsForValue().get(key);
                    int gotNum = 0;
                    if (StringUtils.isNotBlank(value)) {
                        gotNum = Integer.parseInt(value);
                    }
                    if (gotNum == 0) {
                        result.put("times", 1);
                    } else {
                        result.put("times", 2);
                    }
                    return new SerializeObject(ResultType.NORMAL, "00000001", result);
                }
            }
            return new SerializeObjectError("00000005");
        } finally {
            redisGlobalLock.unlock(lockKey);
        }
    }

    @Override
    public SerializeObject getMemberTimes(String memberId, LotteryBean lottery) {
        LotteryJoinMember lotteryJoinMember = lotteryJoinMemberMapper.findByMemberId(memberId, lottery.getId());
        if (lotteryJoinMember == null) {
            return new SerializeObject(ResultType.ERROR, "00000002");
        }
        if (lotteryJoinMember.getTimes() == 0) {
            SimpleDateFormat dateFormat = new SimpleDateFormat(NORMAL_DATE_FORMAT);
            String key = LOTTERY_SHARE_DRAW_NUM_KEY + dateFormat.format(Calendar.getInstance().getTime()) + COLON + memberId+COLON+lottery.getId();
            String value = redisTemplate.opsForValue().get(key);
            if (StringUtils.isNotBlank(value)) {
                int gotNum = Integer.parseInt(value);
                if (gotNum >= lottery.getEverydayMaxNum()) {
                    return new SerializeObject(502, "25000064");
                }
            }
            return new SerializeObject(501, "25000063");
        }
        return new SerializeObject(ResultType.NORMAL, "00000001", lotteryJoinMember.getTimes());
    }

    @Override
    public SerializeObject getDoubleElevenMemberTimes(String memberId, LotteryBean lottery) {
        LotteryJoinMember lotteryJoinMember = lotteryJoinMemberMapper.findByMemberId(memberId, lottery.getId());
        if (lotteryJoinMember == null) {
            return new SerializeObject(ResultType.UNLOGIN, "00000002");
        }
        if (lotteryJoinMember.getTimes() == 0) {
            SimpleDateFormat dateFormat = new SimpleDateFormat(NORMAL_DATE_FORMAT);
            String key = LOTTERY_DOUBLEELEVEN_DRAW_NUM_KEY + dateFormat.format(Calendar.getInstance().getTime()) + COLON + memberId+COLON+lottery.getId();
            String value = redisTemplate.opsForValue().get(key);
            if (StringUtils.isNotBlank(value)) {
                int gotNum = Integer.parseInt(value);
                if (gotNum >= lottery.getEverydayMaxNum()) {
                    return new SerializeObject(502, DateUtils.dateToStr(DateUtils.strToDate(lottery.getEndTime()),"yyyy年MM月dd日"));
                }
            }
            return new SerializeObject(501, "25000090");
        }
        return new SerializeObject(ResultType.NORMAL, "00000001", lotteryJoinMember.getTimes());
    }

    @Override
    public boolean overlayTimes(int lotteryId, int times) {
        if (lotteryId > 0) {
            return lotteryJoinMemberMapper.overlayTimes(lotteryId, times) > 0 ? true : false;
        }
        return false;
    }

    @Override
    public boolean accumulateTimes(int lotteryId, int times) {
        if (lotteryId > 0) {
            return  lotteryJoinMemberMapper.accumulateTimes(lotteryId, times) > 0 ? true : false;
        }
        return false;
    }

    /**
     * 给某用户增加抽奖次数
     *
     * @param lotteryId
     * @param memberId
     * @param times
     * @return
     */
    @Override
    public boolean addMemberLotteryTimes(int lotteryId, String memberId) {
        int rows = lotteryJoinMemberMapper.autoIncreasingTimes(memberId, lotteryId);
        if (rows > 0) {
            return true;
        }
        return false;
    }

    /**
     * 双十一抽奖
     *
     * @param memberId
     * @param lottery
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public SerializeObject doubleElevenDraw(String memberId, LotteryBean lottery) {
        SerializeObject<MemberUserBean> memberBean = memberUserService.findById(memberId);
        String mobile = "";
        if (memberBean != null && memberBean.getData() != null) {
            MemberUserBean memberUserBean = memberBean.getData();
            mobile = memberUserBean.getMobile();
        } else {
            return new SerializeObject(ResultType.ERROR, "00000005");
        }
        String lockKey = "ug:operation:LotteryJoinMemberServiceImpl:draw:"+memberId;
        try {
            if(redisGlobalLock.lock(lockKey, 5000, TimeUnit.MILLISECONDS)) {

                LotteryJoinMember lotteryJoinMember = lotteryJoinMemberMapper.findByMemberId(memberId, lottery.getId());
                if (lotteryJoinMember == null) {
                    return new SerializeObjectError("25000062");
                }
                //当日已抽奖次数
                Map params = new HashMap();
                params.put("memberId",memberId);
                params.put("lotteryId",lottery.getId());
                int outModedLotteryNum = lotteryMemberMapper.countLotteryNumToday(params);
                if (lotteryJoinMember.getTimes() == 0) {
                    //抽奖次数
                    //1.剩余抽奖次数==0，没有回租达到两次，提示回租可增加抽奖次数
                    //2.剩余抽奖次数==0，已回租达到上限，提示当日次数已用完，明天再来
                    try {
                        //回租获得的抽奖次数
                        SimpleDateFormat dateFormat = new SimpleDateFormat(NORMAL_DATE_FORMAT);
                        String key = LOTTERY_DOUBLEELEVEN_DRAW_NUM_KEY + dateFormat.format(Calendar.getInstance().getTime()) + COLON + memberId+COLON+lottery.getId();
                        String value = redisTemplate.opsForValue().get(key);
                        if (StringUtils.isNotBlank(value)) {
                            int gotNum = Integer.parseInt(value);
                            if (gotNum >= lottery.getEverydayMaxNum()) {
                                return new SerializeObject(ResultType.EXCEPTION, "25000091");
                            } else {
                                return new SerializeObject(ResultType.EXCEPTION, "25000090");
                            }
                        }
                        if (StringUtils.isBlank(value)) {
                            return new SerializeObject(ResultType.EXCEPTION, "25000090");
                        }
                    } catch (Exception e) {
                        logger.info("双十一抽奖，redis获取回租奖励次数失败！",e);
                    }

                    if (outModedLotteryNum >= lottery.getEverydayMaxNum() + lottery.getEverydayNum()){
                        return new SerializeObject(ResultType.EXCEPTION, "25000091");
                    }
                }

                List<LotteryPrize> prizes = lotteryPrizeMapper.selectByLotteryId(lottery.getId());
                if (prizes == null || prizes.size() == 0) {
                    return new SerializeObjectError("00000002");
                }
                List<LotteryPrize> drawPrizes = new ArrayList<LotteryPrize>();
                for (LotteryPrize prize : prizes) {
                    if (prize.getQuantityLimit() == 0) {
                        drawPrizes.add(prize);
                    } else if (prize.getQuantity() > 0) {
                        drawPrizes.add(prize);
                    }
                }
                if (drawPrizes == null || drawPrizes.size() == 0) {
                    return new SerializeObjectError("25000065");
                }
                LotteryPrize prize = getPrize(drawPrizes);
                LotteryMember lotteryMember = new LotteryMember();
                lotteryMember.setAddTime(LocalDateTime.now());
                if (lottery.getGrantingMethod() == 0) {
                    lotteryMember.setGetTime(LocalDateTime.now());
                    lotteryMember.setStatus(1);
                }
                lotteryMember.setLotteryId(lottery.getId());
                lotteryMember.setMemberId(memberId);
                lotteryMember.setPrizeId(prize.getId());
                if (prize.getType() != LotteryPrizeTypeEnum.UN_PRIZE.getType()) {
                    lotteryMember.setRewardsStatus(1);
                }
                int rows = lotteryMemberMapper.insert(lotteryMember);
                if (rows > 0) {
                    //奖品库存减
                    if (prize.getQuantityLimit() != 0) {
                        rows = lotteryPrizeMapper.decreaseQuantity(prize.getId());
                        Ensure.that(rows).isLt(1,"00000005");
                    }
                    //抽奖次数减
                    rows = lotteryJoinMemberMapper.decreaseTimes(memberId, lottery.getId());
                    Ensure.that(rows).isLt(1,"00000005");
                    double amount = 0;
                    if (lottery.getGrantingMethod() == 0) {
                        if (prize.getType() == LotteryPrizeTypeEnum.CASH.getType()) {
                            SerializeObject bean = memberAccountService.inviteReturnCash(memberId, prize.getAmount(), TradeType.CASH_REWARDS.getValue());
                            if(bean != null && bean.getCode() == ResultType.NORMAL) {
                                amount = prize.getAmount().doubleValue();
                                Msg msg = new Msg();
                                msg.setMemberId(memberId);
                                msg.setMobile(mobile);
                                msg.setType(cn.ug.msg.bean.status.CommonConstants.MsgType.CASH_REWARDS.getIndex());
                                Map<String, String> paramMap = new HashMap<>();
                                paramMap.put("amount", String.valueOf(prize.getAmount()));
                                msg.setParamMap(paramMap);
                                amqpTemplate.convertAndSend(QUEUE_MSG_SEND, msg);
                            } else {
                                Ensure.that(0).isLt(1,"00000005");
                            }
                        } else if (prize.getType() == LotteryPrizeTypeEnum.GOLD.getType()) {
                            int tradeType = BillGoldTradeType.LOTTERY.getValue();
                            SerializeObject bean = memberGoldService.investRebate(memberId, prize.getAmount(), tradeType);
                            if(bean != null && bean.getCode() == ResultType.NORMAL) {
                                amount = prize.getAmount().doubleValue();
                                Msg msg = new Msg();
                                msg.setMemberId(memberId);
                                msg.setMobile(mobile);
                                msg.setType(cn.ug.msg.bean.status.CommonConstants.MsgType.GUESS_GOLD_PRICE.getIndex());
                                Map<String, String> paramMap = new HashMap<>();
                                paramMap.put("weight", String.valueOf(prize.getAmount()));
                                msg.setParamMap(paramMap);
                                amqpTemplate.convertAndSend(QUEUE_MSG_SEND, msg);
                            } else {
                                Ensure.that(0).isLt(1,"00000005");
                            }
                        } else if (prize.getType() == LotteryPrizeTypeEnum.KICKBACK.getType()) {
                            if (StringUtils.isBlank(prize.getCouponIds())) {
                                Ensure.that(0).isLt(1,"00000002");
                            }
                            String[] infos = StringUtils.split(prize.getCouponIds(), COMMA);
                            int num = ThreadLocalRandom.current().nextInt(0, infos.length);
                            String couponId = infos[num];
                            SerializeObject bean = couponRepertoryService.giveCoupon(memberId, couponId);
                            if(bean != null && bean.getCode() == ResultType.NORMAL && bean.getData() != null) {
                                amount = Double.parseDouble(bean.getData().toString());
                                Msg msg = new Msg();
                                msg.setMemberId(memberId);
                                msg.setMobile(mobile);
                                msg.setType(cn.ug.msg.bean.status.CommonConstants.MsgType.COUPON_NOTIFY.getIndex());
                                Map<String, String> paramMap = new HashMap<>();
                                paramMap.put("activityName", lottery.getName());
                                paramMap.put("amount", bean.getData().toString());
                                msg.setParamMap(paramMap);
                                amqpTemplate.convertAndSend(QUEUE_MSG_SEND, msg);
                            } else {
                                Ensure.that(0).isLt(1,"00000005");
                            }
                        } else if (prize.getType() == LotteryPrizeTypeEnum.INTEREST.getType()) {
                            if (StringUtils.isBlank(prize.getCouponIds())) {
                                Ensure.that(0).isLt(1,"00000002");
                            }
                            String[] infos = StringUtils.split(prize.getCouponIds(), COMMA);
                            int num = ThreadLocalRandom.current().nextInt(0, infos.length);
                            String couponId = infos[num];
                            SerializeObject bean = couponRepertoryService.giveCoupon(memberId, couponId);
                            if(bean != null && bean.getCode() == ResultType.NORMAL && bean.getData() != null) {
                                amount = Double.parseDouble(bean.getData().toString());
                                Msg msg = new Msg();
                                msg.setMemberId(memberId);
                                msg.setMobile(mobile);
                                msg.setType(cn.ug.msg.bean.status.CommonConstants.MsgType.TICKET_NOTIFY.getIndex());
                                Map<String, String> paramMap = new HashMap<>();
                                paramMap.put("activityName", lottery.getName());
                                paramMap.put("amount", bean.getData().toString());
                                msg.setParamMap(paramMap);
                                amqpTemplate.convertAndSend(QUEUE_MSG_SEND, msg);
                            } else {
                                Ensure.that(0).isLt(1,"00000005");
                            }
                        } else if (prize.getType() == LotteryPrizeTypeEnum.GOLD_PACKET.getType()) {
                            if (StringUtils.isBlank(prize.getCouponIds())) {
                                Ensure.that(0).isLt(1,"00000002");
                            }
                            String[] infos = StringUtils.split(prize.getCouponIds(), COMMA);
                            int num = ThreadLocalRandom.current().nextInt(0, infos.length);
                            String couponId = infos[num];
                            SerializeObject bean = couponRepertoryService.giveCoupon(memberId, couponId);
                            CouponRepertoryBean couponRepertoryBean = null;
                            SerializeObject data = couponRepertoryService.findCouponById(Integer.valueOf(couponId));
                            if (data != null && data.getData() != null ) {
                                couponRepertoryBean = (CouponRepertoryBean)data.getData();
                            }
                            if (couponRepertoryBean != null) {
                                amount = couponRepertoryBean.getDiscountAmount();
                            }
                            if(bean != null && bean.getCode() == ResultType.NORMAL && bean.getData() != null) {
                                //amount = Double.parseDouble(bean.getData().toString());
                                Msg msg = new Msg();
                                msg.setMemberId(memberId);
                                msg.setMobile(mobile);
                                msg.setType(cn.ug.msg.bean.status.CommonConstants.MsgType.COUPON_NOTIFY.getIndex());
                                Map<String, String> paramMap = new HashMap<>();
                                paramMap.put("activityName", lottery.getName());
                                paramMap.put("amount", bean.getData().toString());
                                msg.setParamMap(paramMap);
                                amqpTemplate.convertAndSend(QUEUE_MSG_SEND, msg);
                            } else {
                                Ensure.that(0).isLt(1,"00000005");
                            }
                        }
                    }
                    lotteryMember.setAmount(amount);
                    lotteryMemberMapper.update(lotteryMember);
                    JSONObject result = new JSONObject();
                    result.put("prizeName", prize.getName());
                    result.put("amount", amount);
                    result.put("type", prize.getType());
                    /*SimpleDateFormat dateFormat = new SimpleDateFormat(NORMAL_DATE_FORMAT);
                    String key = LOTTERY_SHARE_DRAW_NUM_KEY + dateFormat.format(Calendar.getInstance().getTime()) + COLON + memberId+COLON+lottery.getId();
                    String value = redisTemplate.opsForValue().get(key);*/
                    //1.还可以通过回租获取抽奖次数
                    //0.抽奖次数达到上限
                    if (outModedLotteryNum + 1 >= lottery.getEverydayMaxNum() + lottery.getEverydayNum()){
                        result.put("times", 0);
                    } else {
                        result.put("times", 1);
                    }

                    logger.info("用户【"+ memberBean.getData().getName()+ "】"+"抽奖结果:"+result.toJSONString());
                    return new SerializeObject(ResultType.NORMAL, "00000001", result);
                }
            }
            return new SerializeObjectError("00000005");
        } finally {
            redisGlobalLock.unlock(lockKey);
        }
    }

    /**
     * 根据用户id，查询用户参加的活动
     *
     * @param memberId
     * @return
     */
    @Override
    public SerializeObject<LotteryJoin> findJoinLotteryByMember(String memberId) {
        LotteryJoinMember lotteryJoinMember = lotteryJoinMemberMapper.findJoinLottery(memberId);
        if (lotteryJoinMember == null) {
            return new SerializeObject(ResultType.ERROR, lotteryJoinMember);
        }
        LotteryJoin lotteryJoin = new LotteryJoin();
        BeanUtils.copyProperties(lotteryJoinMember,lotteryJoin);
        lotteryJoin.setAddTime(UF.getFormatDateTime(lotteryJoinMember.getAddTime()));
        //LotteryJoin lotteryJoin = dozerBeanMapper.map(lotteryJoinMember, LotteryJoin.class);
        return new SerializeObject(ResultType.NORMAL, lotteryJoin);
    }

    private LotteryPrize getPrize(List<LotteryPrize> prizes) {
        //奖品总数
        int size = prizes.size();
        //计算总概率
        BigDecimal sumProbability = BigDecimal.ZERO;
        for (LotteryPrize prize : prizes) {
            sumProbability = sumProbability.add(prize.getProbability());
        }

        //计算每个奖品的概率区间
        //例如奖品A概率区间0-0.1  奖品B概率区间 0.1-0.5 奖品C概率区间0.5-1
        //每个奖品的中奖率越大，所占的概率区间就越大
        List<Double> sortAwardProbabilityList = new ArrayList<Double>(size);
        BigDecimal tempSumProbability = BigDecimal.ZERO;
        for (LotteryPrize prize : prizes) {
            tempSumProbability = tempSumProbability.add(prize.getProbability());
            sortAwardProbabilityList.add(tempSumProbability.doubleValue() / sumProbability.doubleValue());
        }

        //产生0-1之间的随机数
        //随机数在哪个概率区间内，则是哪个奖品
        double randomDouble = Math.random();
        //加入到概率区间中，排序后，返回的下标则是awardList中中奖的下标
        sortAwardProbabilityList.add(randomDouble);
        Collections.sort(sortAwardProbabilityList);
        int lotteryIndex = sortAwardProbabilityList.indexOf(randomDouble);
        return prizes.get(lotteryIndex);
    }
}
